﻿using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Mvc;
using SportsPlatform.RedisService;
using System.Threading.Tasks;
using System;
using SportsPlatform.Global;
using SportsPlatform.Base;
using Microsoft.AspNetCore.Authorization;
using System.IdentityModel.Tokens.Jwt;
using System.Net;
using SportsPlatform.Global.JwtSecurity;
using Polly.Caching;

namespace SportsPlatform.Controllers
{
    /// <summary>
    /// Jwt接口认证控制器
    /// </summary>
    [Microsoft.AspNetCore.Mvc.Route("api/[controller]/[action]")]
    public class JwtSecurityAuthenticationController : SportsPlatformControllerBase
    {
        #region 属性及构造函数

        /// <summary>
        /// Redis接口实例
        /// </summary>
        private readonly IRedisService redisService;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="redisService"></param>
        public JwtSecurityAuthenticationController(IRedisService redisService)
        {
            this.redisService = redisService;
        }

        #endregion

        #region 获取盐份

        /// <summary>
        /// 获取盐份
        /// </summary>
        /// <param name="userName">用户名</param>
        /// <returns>盐份</returns>
        [HttpGet]
        [AllowAnonymous]
        public async Task<ResultDto<Guid>> Get(string userName)
        {
            ResultDto<Guid> res = new ResultDto<Guid>();
            if (String.IsNullOrEmpty(userName))
            {
                throw new UldAdminCustomException("用户名称不能为空");
            }

            if (userName.Equals(UldAdminGlobalContext.JwtSettings.DefaultUser))
            {
                var salt = Guid.NewGuid();
                var encrytStr = UldHashUtil.HashToHexString512(UldAdminGlobalContext.JwtSettings.DefaultPassword + salt);
                await redisService.SetAsync(salt.ToString(), encrytStr, UldAdminGlobalContext.JwtSettings.SaltExpiration);
                res.Code = 200;
                res.Data = salt;
                res.IsSuccess = true;
                res.Message = "OK";
                return res;
            }

            throw new UldAdminCustomException("没有内容");
        }

        #endregion

        #region 获取Jwt口令

        /// <summary>
        /// Jwt身份认证接口
        /// </summary>
        /// <param name="jwtAuthentication">身份信息</param>
        /// <returns>token信息</returns>
        [HttpPost]
        [AllowAnonymous]
        public async Task<ResultDto<object>> Post([FromBody] JwtAuthentication jwtAuthentication)
        {
            ResultDto<object> resultDto = new ResultDto<object>();
            if (!ModelState.IsValid)
            {
                throw new UldAdminCustomException("模型状态无效");
            }

            var encrytStr = String.Empty;

            if (await redisService.ExistsAsync(new string[] { jwtAuthentication.Salt }) > 0)
            {
                encrytStr = await redisService.GetAsync(jwtAuthentication.Salt);
            }

            if (String.IsNullOrEmpty(encrytStr))
            {
                throw new UldAdminCustomException("盐未验证");
            }

            if (jwtAuthentication.UserName.Equals(UldAdminGlobalContext.JwtSettings.DefaultUser)
                && jwtAuthentication.Password.Equals(encrytStr, StringComparison.OrdinalIgnoreCase))
            {
                await redisService.DeleteAsync(new string[] { jwtAuthentication.Salt });

                var token = JwtAuthentication.GetJwtSecurityToken(jwtAuthentication.UserName);

                //设置RefreshToken有效期
                await this.redisService.SetAsync(token.Id, token.Id, 12 * 3 * UldAdminGlobalContext.JwtSettings.TokenExpiration * 60);

                resultDto.Code = 200;
                resultDto.Message = "OK,expiration:" + token.ValidTo.ToLocalTime();
                resultDto.IsSuccess = true;
                resultDto.Data = new { AccessToken = new JwtSecurityTokenHandler().WriteToken(token), RefreshToken = token.Id };

                return resultDto;
            }

            throw new UldAdminCustomException("未找到Token");
        }

        #endregion


        #region 刷新Jwt口令

        /// <summary>  rt er    
        /// 刷新口令
        /// </summary>
        /// <returns>ActionResult</returns>
        [HttpGet]
        [AllowAnonymous]
        public async Task<ResultDto<object>> RefreshToken()
        {
            String accessToken = this.HttpContext.Request.Headers["Authorization"];
            String refreshToken = this.HttpContext.Request.Headers["RefreshToken"];
            ResultDto<object> resultDto = new ResultDto<object>();
            var jwtToken = new JwtSecurityTokenHandler().ReadJwtToken(accessToken.Replace("Bearer ", ""));
            if (jwtToken.Id.Equals(refreshToken))
            {
                var rtValue = await this.redisService.GetAsync(refreshToken);
                if (!String.IsNullOrEmpty(rtValue) && rtValue.Equals(refreshToken))
                {
                    //删除旧RefreshToken
                    await this.redisService.DeleteAsync(new String[] { refreshToken });

                    var token = JwtAuthentication.GetJwtSecurityToken(UldAdminGlobalContext.JwtSettings.DefaultUser);

                    //设置RefreshToken有效期
                    await this.redisService.SetAsync(token.Id, token.Id, 12 * 3 * UldAdminGlobalContext.JwtSettings.TokenExpiration * 60);

                    resultDto.Code = 200;
                    resultDto.Message = "OK,expiration:" + token.ValidTo.ToLocalTime();
                    resultDto.IsSuccess = true;
                    resultDto.Data = new { AccessToken = new JwtSecurityTokenHandler().WriteToken(token), RefreshToken = token.Id };

                    return resultDto;
                }
            }

            throw new UldAdminCustomException("不允许刷新Token");
        }

        #endregion


    }
}
